﻿using Common;
using Device;
using LiveCharts;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using T68Control.Procdure;
using T68Control.S12L_M1;
using T68Control.T68;
using T68Control.View;
using VM.PlatformSDKCS;
using TestItem2 = T68Control.S12L_M1.TestItem2;

namespace T68Control.ViewModel
{
    internal class HomeViewModel : NotifyBase
    {
        private int logIndex = 1;

        private string _log;

        public string Log
        {
            get { return _log; }
            set
            {
                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    _log = $"[{logIndex++.ToString()}] {value}";
                    this.DoNotify();
                }));
            }
        }

        private string _sn;

        public string SN
        {
            get { return _sn; }
            set
            {
                _sn = value;
                this.DoNotify();
            }
        }

        private int _okCount;

        public int OKCount
        {
            get { return _okCount; }
            set
            {
                _okCount = value;
                this.DoNotify();
                Counter.OkCount = value;
                Counter.Save(Counter);
            }
        }

        private int _ngCount;

        public int NGCount
        {
            get { return _ngCount; }
            set
            {
                _ngCount = value;
                this.DoNotify();
                Counter.NgCount = value;
                Counter.Save(Counter);
            }
        }

        private bool? _result;

        public bool? Result
        {
            get { return _result; }
            set
            {
                _result = value;
                this.DoNotify();
            }
        }

        private bool? _result1;

        public bool? Result1
        {
            get { return _result1; }
            set
            {
                _result1 = value;
                this.DoNotify();
            }
        }

        private bool? _result2;

        public bool? Result2
        {
            get { return _result2; }
            set
            {
                _result2 = value;
                this.DoNotify();
            }
        }

        public Counter Counter { get; set; }
        public Func<ChartPoint, string> PointLabel { get; set; }

        public ObservableCollection<TestItem2> Data { get; set; }

        private TestItem2 _selectedItem;

        public TestItem2 SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                this.DoNotify();
            }
        }

        private int _selectedIndex;

        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set
            {
                _selectedIndex = value;
                this.DoNotify();
            }
        }

        private ListCollectionView _dataView;

        public ListCollectionView DataView
        {
            get { return _dataView; }
            set
            {
                _dataView = value;
                this.DoNotify();
            }
        }

        private int _processMax;

        public int ProcessMax
        {
            get { return _processMax; }
            set
            {
                _processMax = value;
                this.DoNotify();
            }
        }

        private int _processValue;

        public int ProcessValue
        {
            get { return _processValue; }
            set
            {
                _processValue = value;
                this.DoNotify();
            }
        }

        public Config Config { get; set; }

        public HomeViewModel(string str)
        {
        }

        public HomeViewModel()
        {
            PassNgCountClearCommand = new CommandBase(PassNgCountClear);
            StartCommand = new CommandBase(Start);
            ResetCommand = new CommandBase(Reset);
            LoadCommand = new CommandBase(Load);
            ImagesShowCommand = new CommandBase(ShowImageEvent);
            startTime = DateTime.Now; // 获取当前时间
            try
            {
                Result = null;
                Result1 = null;
                Result2 = null;
                SN = "report";
                Counter = Counter.Load();
                OKCount = Counter.OkCount;
                NGCount = Counter.NgCount;
                PointLabel = chartPoint =>
                string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);

                PointLabel = chartPoint =>
                      string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);

                Global.SetLog += new Action<string>((log) =>
                {
                    System.Windows.Application.Current.Dispatcher.Invoke(() => { Log = log; });
                });
                Config = Config.Load();
                VisionMasterHelper.Init();
                VisionMasterHelper.LoadVisionProj(Config.VisionFilePath);
                InitDevice();

                //创建文件定时拷贝任务

                Timer timer = new Timer(fileBackup, null, 0, 1000 * 60 * 60);

                //OnlyViewTest = true;
                Log = "初始化完成";
            }
            catch (Exception ex)
            {
                Mylog.Error(ex, ex.Message);
                Log = ex.Message + "!";
            }
        }

        private void fileBackup(object state)
        {
            var datetime = DateTime.Now.AddHours(-1);
            var result = EnhancedFileCopyService.CopyToTwoLocationsAndDelete(Config.FailImagePath, datetime);
            Mylog.Info(result.ToString());
            result = EnhancedFileCopyService.CopyToTwoLocationsAndDelete(@"D:\T68Conrol_images", datetime);
            Mylog.Info(result.ToString());
            result = EnhancedFileCopyService.CopyToTwoLocationsAndDelete(@"D:\T68Control_pass_images", datetime);
            Mylog.Info(result.ToString());
        }

        private void Load(object obj)
        {
            if (Global.IsConfigChanged)
            {
                ReloadTestFile();
                Global.IsConfigChanged = false;
            }
        }

        private void ReloadTestFile()
        {
            try
            {
                Config = Config.Load();
                LoadTestConfig(Config.TestFilePath);
                //DataView = new ListCollectionView(Data);
                //DataView.Filter = Filter;
                Log = "测试配置加载完成";
                if (!File.Exists(Global.OddLinePointFile)
                    || !File.Exists(Global.EvenLinePointFile)
                    || !File.Exists(Global.OddColumnPointFile)
                    || !File.Exists(Global.EvenColumnPointFile))
                {
                    Log = "坐标文件不存在,请先完成棋格标定!";
                    return;
                }

                string strp1 = File.ReadAllText(Global.OddLinePointFile);
                string strp2 = File.ReadAllText(Global.EvenLinePointFile);
                string strp3 = File.ReadAllText(Global.OddColumnPointFile);
                string strp4 = File.ReadAllText(Global.EvenColumnPointFile);
                LedTest.Init(strp1, strp2, strp3, strp4, 5);
                Log = "KD树构建完成";
            }
            catch (Exception ex)
            {
                Log = ex.Message + "!";
            }
        }

        private void Reset(object obj)
        {
            if (_isEmgStop)
            {
                Log = "设备急停!";
                return;
            }
            if (Global.IsSafeLine)
            {
                Log = "安全光栅触发!";
                return;
            }
            if (Global.IsBusy)
            {
                Log = "正在执行其他操作,请完成后再尝试!";
                return;
            }
            Global.IsBusy = true;
            try
            {
                _set_emg_lisht = false;
                Result = null;
                Result1 = null;
                Result2 = null;
                SN1 = "";
                SN2 = "";
                SNInputList.Clear();
                if (OnlyTestPB23)
                {
                    SNInputFocusSwitchAction?.Invoke(2);
                }
                else
                {
                    SNInputFocusSwitchAction?.Invoke(1);
                }
                Machine.IOModule.SetDOValue((int)DODefine.Yellow, 1);
                Machine.IOModule.SetDOValue((int)DODefine.Green, 0);
                Machine.IOModule.SetDOValue((int)DODefine.Red, 0);
                Machine.IOModule.SetDOValue((int)DODefine.Power1, 0);
                Machine.IOModule.SetDOValue((int)DODefine.Power2, 0);
                Machine.IOModule.SetDOValue((int)DODefine.Comm1, 0);
                Machine.IOModule.SetDOValue((int)DODefine.Comm2, 0);

                //PQW_IO.SetDO(1, 1, false);//气缸复位
                Log = "复位完成";
            }
            catch (Exception ex)
            {
                Log = ex.Message + "!";
            }
            finally
            {
                Global.IsBusy = false;
            }
        }

        private void StepTest(object obj)
        {
        }

        private bool isTest = false;
        private bool _set_emg_lisht = false;

        private void Start(object obj)
        {
            Task.Run(() =>
            {
                if (_isEmgStop)
                {
                    Log = "设备急停!";
                    return;
                }
                if (Global.IsSafeLine)
                {
                    Log = "安全光幕触发!";
                    return;
                }
                if (isTest)
                {
                    return;
                }
                isTest = true;
                if (Global.IsBusy)
                {
                    Log = "正在执行其他操作,请完成后再尝试!";
                    return;
                }
                Global.IsBusy = true;
                try
                {
                    startTime = DateTime.Now; // 获取当前时间
                    Stopwatch sw = Stopwatch.StartNew();
                    TestT68Control();
                    Log = $"测试耗时{sw.ElapsedMilliseconds / 1000.0}s";
                    Result1 = PBData[0].Where(x => x.Result == "FAIL").Count() == 0 ? true : false;
                    Result2 = PBData[1].Where(x => x.Result == "FAIL").Count() == 0 ? true : false;

                    Result = Result1 | Result2;
                    if ((bool)Result)
                    {
                        OKCount++;
                        Machine.IOModule.SetDOValue((int)DODefine.Yellow, 1);
                    }
                    else
                    {
                        NGCount++;
                        _set_emg_lisht = true;
                        Task.Run(() =>
                        {
                            int temp = 0;
                            while (_set_emg_lisht)
                            {
                                Machine.IOModule.SetDOValue((int)DODefine.Red, 1);
                                Thread.Sleep(1000);
                                Machine.IOModule.SetDOValue((int)DODefine.Red, 0);
                                Thread.Sleep(1000);
                                if (temp > 10) { _set_emg_lisht = false; }
                                else
                                {
                                    temp++;
                                }
                            }
                        });
                    }
                    Machine.IOModule.SetDOValue((int)DODefine.Power1, 0);
                    Machine.IOModule.SetDOValue((int)DODefine.Power2, 0);
                    Machine.IOModule.SetDOValue((int)DODefine.Comm1, 0);
                    Machine.IOModule.SetDOValue((int)DODefine.Comm2, 0);
                }
                catch (VmException vmex)
                {
                    Log = vmex.Message + "!";
                }
                catch (Exception ex)
                {
                    Log = ex.Message + "!";
                }
                finally
                {
                    Global.T68.Close();
                    SN1 = "";
                    SN2 = "";
                    SNInputList.Clear();

                    isTest = false;
                    Global.IsBusy = false;
                    SNInputFocusSwitchAction?.Invoke(1);
                }
            });
        }

        private void InitDevice()
        {
            Config config = Config.Load();
            Global.T68 = new T68PBControl();

            DM3058E.Connect(config.DM3058EPort);
            IOModule io = new IOModule();
            io.Connect();
            Machine.IOModule = io;
            IV_3003T.Connect(config.IV3003TPort);
            PQW_IO.Connect(config.PQW_IO_Port);
            RU_18_10001.Connect(config.RU18Port);

            IV_3003T.SwitchCh((IV3003T_CH_ENUM)1);
            IV_3003T.SetVoltage(5);
            IV_3003T.SetCurrent(1);
            IV_3003T.SwitchCh((IV3003T_CH_ENUM)2);
            IV_3003T.SetVoltage(5);
            IV_3003T.SetCurrent(1);
            IV_3003T.SwitchCh((IV3003T_CH_ENUM)3);
            IV_3003T.SetVoltage(5);
            IV_3003T.SetCurrent(1);
            DM3058E.SetFunction(Function.DCI);
            DM3058E.SetRange(10.0);
            IV_3003T.SetChStatus(1);
            RU_18_10001.SetVoltage(9);
            RU_18_10001.SetCurrent(6);
            RU_18_10001.SetStatus(true);
            io.ListDIChanged.Add(new DIChanged { DIndex = (int)DIDefine.EmgStop, ConditionValue = false, DIChangedEvent = EmgStopAction });
            io.ListDIChanged.Add(new DIChanged { DIndex = (int)DIDefine.EmgStop, ConditionValue = true, DIChangedEvent = () => { _isEmgStop = false; } });
            io.ListDIChanged.Add(new DIChanged { DIndex = (int)DIDefine.Start, ConditionValue = true, DIChangedEvent = StartAction });
            io.ListDIChanged.Add(new DIChanged { DIndex = (int)DIDefine.SafeLine, ConditionValue = false, DIChangedEvent = () => { Global.IsSafeLine = true; } });
            io.ListDIChanged.Add(new DIChanged { DIndex = (int)DIDefine.SafeLine, ConditionValue = true, DIChangedEvent = () => { Global.IsSafeLine = false; } });
            Task.Run(() =>
            {
                Global.TcpServer = new TCPServer();
                Global.TcpServer.Connect();
            });
            //设置相机曝光时间为10000
            CameraTool.SetExposureTime(10000);

            SNInputFocusSwitchAction?.Invoke(1);
        }

        private void StartAction()
        {
            Start(null);
        }

        private bool _isEmgStop;
        //private bool Global.IsSafeLine;

        private void EmgStopAction()
        {
            if (!_isEmgStop)
            {
                Log = "设备急停!";
                _isEmgStop = true;
            }
        }

        private void LoadTestConfig(string path)
        {
            //Data = new ObservableCollection<TestItem2>();
            TestModul.ParseExcelFile(path);
            //foreach (var item in TestModul.TestItems)
            //{
            //    Data.Add(item);
            //}
        }

        private void PassNgCountClear(object obj)
        {
            OKCount = 0;
            NGCount = 0;
        }

        public CommandBase PassNgCountClearCommand { get; set; }
        public CommandBase StartCommand { get; set; }
        public CommandBase ResetCommand { get; set; }
        public CommandBase ImagesShowCommand { get; set; }
        public CommandBase LoadCommand { get; set; }

        #region S12L-M1

        private bool _onlyTestPB23;

        public bool OnlyTestPB23
        {
            get { return _onlyTestPB23; }
            set
            {
                _onlyTestPB23 = value;
                this.DoNotify();

                SNInputFocusSwitchAction.Invoke(value ? 2 : 1);
            }
        }

        public Action<int> SNInputFocusSwitchAction;
        private List<string> SNInputList = new List<string>();
        private string _sn1;

        public string SN1
        {
            get { return _sn1; }
            set
            {
                _sn1 = value;
                this.DoNotify();

                if (value.Length >= Config.SNLength)
                {
                    if (SNInputList.Contains(value))
                    {
                        SN1 = "";
                        SNInputFocusSwitchAction.Invoke(1);
                        Log = "二维码重复!";
                    }
                    else
                    {
                        SNInputList.Add(value);
                        SNInputFocusSwitchAction.Invoke(2);
                    }
                }
            }
        }

        private string _sn2;

        public string SN2
        {
            get { return _sn2; }
            set
            {
                _sn2 = value;
                this.DoNotify();

                if (value.Length >= Config.SNLength)
                {
                    if (SNInputList.Contains(value))
                    {
                        SN2 = "";
                        SNInputFocusSwitchAction.Invoke(2);
                        Log = "二维码重复!";
                    }
                    else
                    {
                        SNInputList.Add(value);
                        SNInputFocusSwitchAction.Invoke(3);
                    }
                }
            }
        }

        private Dictionary<int, List<TestItem2>> PBData;

        #endregion S12L-M1

        #region imageHelper

        public List<string> ImagePaths = new List<string>();
        private DateTime startTime;

        public void LoadImage(string _folderPath)
        {
            //startTime = new DateTime(2024, 8, 24, 2, 49, 50);
            // 只获取JPG格式的图片
            var latestImages = Directory.GetFiles(_folderPath, "*.jpg", SearchOption.TopDirectoryOnly)
                .Select(f => new FileInfo(f))
                .OrderByDescending(f => f.CreationTime)
                .Take(10) // 获取最新的10张JPG图片
                .Where(file => file.CreationTime > startTime)
                .Select(f => f.FullName)
                .ToList();

            var latestImagess = Directory.GetFiles(_folderPath, "*.jpg", SearchOption.TopDirectoryOnly)
                .Select(f => new FileInfo(f))
                //.OrderByDescending(f => f.CreationTimeUtc)
                //.Take(10) // 获取最新的10张JPG图片
                .Where(file => file.CreationTimeUtc > startTime)
                .Select(f => f.FullName)
                .ToList();
            //DirectoryInfo di = new DirectoryInfo(_folderPath);
            //FileInfo[] files = di.GetFiles("*.jpg"); // 获取所有JPG文件

            //var recentJpgFiles = files
            //    .Where(file => file.CreationTimeUtc > startTime) // 筛选出当前时间之后创建的文件
            //    .ToArray();

            //foreach (var file in recentJpgFiles)
            //{
            //    Console.WriteLine(file.FullName); // 打印文件的全名
            //}

            ImagePaths.Clear();
            foreach (var imagePath in latestImages)
            {
                ImagePaths.Add(imagePath);
            }
        }

        private void ShowImageEvent(object obj)
        {
            try
            {
                if (_isEmgStop)
                {
                    Log = "设备急停!";
                    return;
                }
                if (Global.IsSafeLine)
                {
                    Log = "安全光幕触发!";
                    return;
                }
                // 视觉方案校验
                if (!VisionMasterHelper.vmPorjLoaded)
                {
                    Log = "请等待视觉方案加载完成";
                    return;
                }
                if (isTest)
                {
                    Log = "请完成测试再查看!";
                    return;
                }
                if (Global.IsBusy)
                {
                    Log = "正在执行其他操作,请完成后再尝试!";
                    return;
                }
                Global.IsBusy = true;
                var _failImagePath = Config.FailImagePath;
                if (!Directory.Exists(_failImagePath))
                {
                    MessageBox.Show("文件夹不存在,请联系管理员!");
                    return;
                }
                LoadImage(_failImagePath);
                if (ImagePaths.Count > 0)
                {
                    var imagePopupWindow = new ImagePopupWindow(ImagePaths);
                    imagePopupWindow.ShowDialog();
                }
                else
                {
                    MessageBox.Show("无NG图片!");
                }
            }
            catch (Exception ex)
            {
                Log = ex.Message + "!";
            }
            finally
            {
                Global.IsBusy = false;
            }
        }

        #endregion imageHelper

        #region T60Control

        private void TestT68ControlVisonAndCurrent(int mode, string desc, VisionProcessID visionProcessID, string varSn = "allSn")
        {
            string processName = desc + "测试";
            Log = processName;
            SN = desc + "_" + SN1 + "_" + SN2;
            VisionTool.SetGlobalVar(varSn, SN);

            Global.T68.SetStrongControlMode(mode);
            Thread.Sleep(1000);
            VisionMasterHelper.ExecVisionFlow(processName, (uint)visionProcessID);

            for (int pbIndex = 0; pbIndex < 2; pbIndex++)
            {
                var ledLeft = VisionTool.GetGlobalVar($"pb{pbIndex * 2 + 1}Ret");
                var ledRight = VisionTool.GetGlobalVar($"pb{pbIndex * 2 + 2}Ret");
                var strPbResult = ledLeft + ledRight == "11" ? "PASS" : "FAIL";
                Log = $"工位{pbIndex + 1}{desc}视觉测试{strPbResult}" + (strPbResult == "FAIL" ? "!" : "");
                PBData[pbIndex].Add(new TestItem2 { Desc = $"{desc}视觉测试", Result = strPbResult, ErrMsg = "" });
            }
            //TestT68ControlVoltage("9V供电电流(强电模式全亮工况)", 9);
            TestT68ControlVoltage("16V供电电流(强电模式全亮工况)", 16);
            TestT68ControlVoltage("13.5V供电电流(强电模式全亮工况)", 13.5);

            Global.T68.ExitStrongControlMode();
        }

        /// <summary>
        /// 行列测试
        /// </summary>
        /// <param name="mode">点灯模式</param>
        /// <param name="desc"></param>
        /// <param name="offset"></param>
        private void TestT68ControlBDTest(int mode, string desc, VisionProcessID visionProcessID, string varSn = "oddrow", int offset = 0)
        {
            string processName = desc + "测试";
            Log = processName;
            SN = desc + "_" + SN1 + "_" + SN2;
            VisionTool.SetGlobalVar(varSn, SN);

            Global.T68.SetStrongControlMode(mode);
            Thread.Sleep(1000);

            Global.TcpServer.ReceiveReady();
            VisionMasterHelper.ExecVisionFlow(processName, (uint)visionProcessID);
            Global.TcpServer.WaitReceiveFinish();
            Global.T68.ExitStrongControlMode();
            var ledRetStr = Global.TcpServer.Data;

            for (int pbIndex = 0; pbIndex < 2; pbIndex++)
            {
                var ledLeft = LedTest.JudgeLedQGStatus(ledRetStr, (PB)(pbIndex * 2 + 0));
                var ledRight = LedTest.JudgeLedQGStatus(ledRetStr, (PB)(pbIndex * 2 + 1));
                var strPbResult = ledLeft && ledRight ? "PASS" : "FAIL";
                Log = $"工位{pbIndex + 1}{desc}视觉测试{strPbResult}" + (strPbResult == "FAIL" ? "!" : "");
                PBData[pbIndex].Add(new TestItem2 { Desc = $"{desc}视觉测试", Result = strPbResult, ErrMsg = "" });
            }
        }

        public enum T68ControlCanfdReadIndex
        {
            BootVersion,
            AppVersion,
            HardwareVersion,
            SoftwareVersion,
            PartNo,
            MaterialVersion,
            SysVoltate,
            Flash,
            CheckFactoryMode,
            ReadDTC,
            ClearDTC,
            Check0x3FD
        }

        private void T68ControlCanfdReadAndCmp(string desc, T68ControlCanfdReadIndex index)
        {
            for (int pbIndex = 0; pbIndex < 2; pbIndex++)
            {
                string readResult = "";
                switch (index)
                {
                    case T68ControlCanfdReadIndex.BootVersion:
                        readResult = Global.T68.readBootVersion(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.AppVersion:
                        readResult = Global.T68.readAppVersion(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.HardwareVersion:
                        readResult = Global.T68.readHardwareVersion(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.SoftwareVersion:
                        readResult = Global.T68.readSoftwareVersion(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.PartNo:
                        readResult = Global.T68.readPartNumber(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.MaterialVersion:
                        readResult = Global.T68.readMaterialVersion(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.SysVoltate:
                        double vol = Global.T68.readSystemVoltage(pbIndex);
                        double stdvalue = double.Parse(TestModul.TestParams[desc].Param1);
                        double offset = double.Parse(TestModul.TestParams[desc].Param2);
                        double max = stdvalue * (1 + offset / 100);
                        double min = stdvalue * (1 - offset / 100);
                        var strResult2 = (vol <= max && vol >= min) ? "PASS" : "FAIL";
                        Log = $"工位{pbIndex + 1}[{desc}]:[{vol}][{strResult2}]" + (strResult2 == "FAIL" ? "!" : "");
                        PBData[pbIndex].Add(new TestItem2 { Desc = desc, Result = strResult2, ErrMsg = $"{desc}:{readResult}" });
                        if (pbIndex == 0)
                        {
                            continue;
                        }
                        else
                        {
                            return;
                        }

                    default:
                        return;
                }

                var strResult = readResult == TestModul.TestParams[desc].Param1 ? "PASS" : "FAIL";
                Log = $"工位{pbIndex + 1}{desc}:[{readResult}][{strResult}]" + (strResult == "FAIL" ? "!" : "");
                PBData[pbIndex].Add(new TestItem2 { Desc = desc, Result = strResult, ErrMsg = $"{desc}:{readResult}" });
            }
        }

        private void T68ControlCanfdCheck(string desc, T68ControlCanfdReadIndex index)
        {
            bool readResult = false;
            for (int pbIndex = 0; pbIndex < 2; pbIndex++)
            {
                switch (index)
                {
                    case T68ControlCanfdReadIndex.Flash:
                        readResult = Global.T68.verifyFlashFile(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.CheckFactoryMode:
                        readResult = Global.T68.verifyFactoryMode(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.ReadDTC:
                        readResult = Global.T68.verifyReadDTC(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.ClearDTC:
                        readResult = Global.T68.checkClearDTC(pbIndex);
                        break;

                    case T68ControlCanfdReadIndex.Check0x3FD:
                        readResult = Global.T68.Check0x3FDMessageCycle(pbIndex);
                        break;

                    default:
                        return;
                }
                var strResult = readResult ? "PASS" : "FAIL";
                Log = $"工位{pbIndex + 1}[{desc}]:[{strResult}]" + (strResult == "FAIL" ? "!" : "");
                PBData[pbIndex].Add(new TestItem2 { Desc = desc, Result = strResult, ErrMsg = $"{desc}:{readResult}" });
            }
        }

        private void TestT68ControlVoltage(string desc, double voltate)
        {
            RU_18_10001.SetVoltage(voltate);
            Thread.Sleep(1000);
            var current = DM3058E.GetValue();
            double stdVal = double.Parse(TestModul.TestParams[desc].Param1);
            double offset = double.Parse(TestModul.TestParams[desc].Param2);
            double max = stdVal * (1 + offset / 100);
            double min = stdVal * (1 - offset / 100);

            var strResult = (current >= min && current <= max) ? "PASS" : "FAIL";
            Log = $"{desc}:[{current}][{strResult}]" + (strResult == "FAIL" ? "!" : "");
            for (int pbIndex = 0; pbIndex < 2; pbIndex++)
            {
                PBData[pbIndex].Add(new TestItem2 { Desc = desc, Result = strResult, ErrMsg = $"{desc}:{current}" });
            }
        }

        private void TestT68Control()
        {
            Result = null;
            Result1 = null;
            Result2 = null;
            // 参数初始化
            Machine.IOModule.SetDOValue((int)DODefine.Yellow, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Green, 1);
            Machine.IOModule.SetDOValue((int)DODefine.Red, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Power1, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Power2, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Comm1, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Comm2, 0);
            // sn校验

            if (SN1 is null || SN2 is null)
            {
                throw new Exception("SN码长度异常");
            }
            if (SN1.Length != Config.SNLength | SN2.Length != Config.SNLength)
            {
                throw new Exception("SN码长度异常");
            }

            PBData = new Dictionary<int, List<TestItem2>>();
            for (int pbIndex = 0; pbIndex < 2; pbIndex++)
            {
                PBData.Add(pbIndex, new List<TestItem2>());
            }

            // 视觉方案校验
            if (!VisionMasterHelper.vmPorjLoaded)
            {
                Log = "请等待视觉方案加载完成";
                return;
            }
            Log = "开始测试";
            // io 初始化
            Machine.IOModule.SetDOValue((int)DODefine.Green, 1);
            DM3058E.SetFunction(Function.DCI);

            //打开供电 通信
            Machine.IOModule.SetDOValue((int)DODefine.Power1, 1);
            Machine.IOModule.SetDOValue((int)DODefine.Comm1, 1);
            Machine.IOModule.SetDOValue((int)DODefine.Comm2, 1);
            Thread.Sleep(500);
            Log = "控制板上电";

            RU_18_10001.SetVoltage(13.5);
            RU_18_10001.SetCurrent(6);

            TestT68ControlVoltage("9V供电电流", 9);
            TestT68ControlVoltage("13.5V供电电流", 13.5);
            TestT68ControlVoltage("16V供电电流", 16);

            RU_18_10001.SetVoltage(13.5);

            {
                Log = "测试黑屏模式";

                VisionMasterHelper.ExecVisionFlow("黑屏测试", (uint)VisionProcessID.Black);

                for (int pbIndex = 0; pbIndex < 2; pbIndex++)
                {
                    var pbResult = VisionTool.GetGlobalVar($"pb{pbIndex + 1}Ret");
                    var strPbResult = pbResult == "1" ? "PASS" : "FAIL";
                    Log = $"工位{pbIndex + 1}黑屏测试{strPbResult}" + (strPbResult == "FAIL" ? "!" : "");
                    PBData[pbIndex].Add(new TestItem2 { Desc = "黑屏测试", Result = strPbResult, ErrMsg = "" });
                }
                // 检查是否存在 Desc 为 "黑屏测试" 且 Result 为 "FAIL" 的项
                bool hasFail = PBData.Values
                    .SelectMany(list => list)
                    .Any(item => item.Desc == "黑屏测试" && item.Result == "FAIL");

                if (hasFail)
                {
                    // 将所有 Desc 为 "黑屏测试" 的项的 Result 设置为 "FAIL"
                    PBData.Values
                        .SelectMany(list => list)
                        .Where(item => item.Desc == "黑屏测试")
                        .ToList()
                        .ForEach(item => item.Result = "FAIL");
                    return;
                }
            }
            Global.T68.Init();

            Global.T68.StartCharging();
            //Boot版本号
            T68ControlCanfdReadAndCmp("Boot版本号", T68ControlCanfdReadIndex.BootVersion);
            //App版本号
            T68ControlCanfdReadAndCmp("App版本号", T68ControlCanfdReadIndex.AppVersion);
            //硬件版本号
            T68ControlCanfdReadAndCmp("硬件版本号", T68ControlCanfdReadIndex.HardwareVersion);
            //软件版本号
            T68ControlCanfdReadAndCmp("软件版本号", T68ControlCanfdReadIndex.SoftwareVersion);
            //零件号
            T68ControlCanfdReadAndCmp("零件号", T68ControlCanfdReadIndex.PartNo);
            //素材版本号
            T68ControlCanfdReadAndCmp("素材版本号", T68ControlCanfdReadIndex.MaterialVersion);
            //系统电压
            T68ControlCanfdReadAndCmp("系统电压", T68ControlCanfdReadIndex.SysVoltate);

            //0x3FD
            T68ControlCanfdCheck("0x3FD发送周期", T68ControlCanfdReadIndex.Check0x3FD);

            //Flash校验
            T68ControlCanfdCheck("Flash校验", T68ControlCanfdReadIndex.Flash);

            //检查工厂模式
            T68ControlCanfdCheck("检查工厂模式", T68ControlCanfdReadIndex.CheckFactoryMode);

            //DTC读取
            T68ControlCanfdCheck("DTC读取", T68ControlCanfdReadIndex.ReadDTC);

            Thread.Sleep(500);
            //DTC清除
            T68ControlCanfdCheck("DTC清除", T68ControlCanfdReadIndex.ClearDTC);

            TestT68ControlBDTest(1, "奇数行", VisionProcessID.OddLine, "oddrowsn", 0);
            //TestT68ControlBDTest(2, "偶数行", VisionProcessID.EvenLine, "evenrowsn", 4);
            //TestT68ControlBDTest(3, "奇数列", VisionProcessID.OddColumn, "oddcolumnsn", 8);
            //TestT68ControlBDTest(4, "偶数列", VisionProcessID.EvenColumn, "evencolumnsn", 12);
            TestT68ControlVisonAndCurrent(5, "全亮工况", VisionProcessID.AllLight);

            Global.T68.Close();

            Machine.IOModule.SetDOValue((int)DODefine.Power1, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Comm1, 0);
            Machine.IOModule.SetDOValue((int)DODefine.Comm2, 0);

            // 输出测试报告
            if (!Directory.Exists(Config.ReportDirectory))
            {
                Directory.CreateDirectory(Config.ReportDirectory);
            }

            {
                PBData[0][0].SN = SN1;
                PBData[0][0].TestTime = DateTime.Now.ToString("F");
                string pb1TolResult = PBData[0].Where(x => x.Result == "FAIL").Count() > 0 ? "FAIL" : "PASS";
                PBData[0][0].TotalResult = pb1TolResult;
                string fileName = $"{PBData[0][0].SN}_{pb1TolResult}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv";
                string path = $"{Config.ReportDirectory}\\{fileName}";
                string backupPath = $"{Config.ReportBackupDirectory}\\{fileName}";
                new CsvTestReportGenerator().GenerateReport(TestItem2.Headers, PBData[0], path);
                new CsvTestReportGenerator().GenerateReport(TestItem2.Headers, PBData[0], backupPath);
            }

            Log = "输出测试报告";
            {
                PBData[1][0].SN = SN2;
                PBData[1][0].TestTime = DateTime.Now.ToString("F");
                string pb1TolResult = PBData[1].Where(x => x.Result == "FAIL").Count() > 0 ? "FAIL" : "PASS";
                PBData[1][0].TotalResult = pb1TolResult;
                string fileName = $"{PBData[1][0].SN}_{pb1TolResult}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv";
                string path = $"{Config.ReportDirectory}\\{fileName}";
                string backupPath = $"{Config.ReportBackupDirectory}\\{fileName}";
                new CsvTestReportGenerator().GenerateReport(TestItem2.Headers, PBData[1], path);
                new CsvTestReportGenerator().GenerateReport(TestItem2.Headers, PBData[1], backupPath);
            }

            Log = "测试完成";
            Machine.IOModule.SetDOValue((int)DODefine.Green, 0);
        }

        #endregion T60Control
    }
}